package com.ruoyi.web.controller.api;

import cn.hutool.core.date.DateUtil;
import cn.hutool.http.HttpUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.ruoyi.cat.domain.*;
import com.ruoyi.cat.domain.DTO.ArticletaskDTO;
import com.ruoyi.cat.domain.DTO.LatestTaskDTO;
import com.ruoyi.cat.domain.VO.ActivityNumVO;
import com.ruoyi.cat.domain.VO.ArticletaskVO;
import com.ruoyi.cat.domain.VO.ReadNumVO;
import com.ruoyi.cat.service.*;
import com.ruoyi.cat.service.impl.RichTextService;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.domain.model.WxLoginUser;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.utils.IpRegion;
import com.ruoyi.common.utils.bean.BeanUtils;
import com.ruoyi.common.utils.ip.IpUtils;
import com.ruoyi.framework.web.service.WxTokenService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import java.time.Instant;
import java.time.temporal.ChronoUnit;
import java.util.Date;
import java.util.List;
import java.util.concurrent.TimeUnit;

@Api(tags = "api-文章管理相关")
@RestController
@RequestMapping("/api/article")
@Slf4j
public class ArticleController extends BaseController {

    @Autowired
    private WxTokenService wxTokenService;

    @Autowired
    private ICatArticletaskTableService catArticletaskTableService;

    @Autowired
    private ICatActivityTableService iCatActivityTableService;

    @Autowired
    private RichTextService richTextService;

    @Autowired
    private ICatIprecordTableService iCatIprecordTableService;

    @Autowired
    private ICatShareuserTableService iCatShareuserTableService;

    @Autowired
    private ICatBasedataTableService catBasedataTableService;

    @Autowired
    public RedisTemplate redisTemplate;


    @ApiOperation("api-转发和分享")
    @PostMapping("forwardShare")
    public AjaxResult forwardShare(HttpServletRequest request, @RequestBody ActivityNumVO readNumVO) {

        CatArticletaskTable catArticletaskTable = new CatArticletaskTable();
        CatArticletaskTable catArticletaskTable1 = catArticletaskTableService.selectCatArticletaskTableById(readNumVO.getId());
        catArticletaskTable.setId(readNumVO.getId());
        if (catArticletaskTable1.getForwardNum() != null) {
            catArticletaskTable.setForwardNum(catArticletaskTable1.getForwardNum() + 1);
        }else{
            catArticletaskTable.setForwardNum(1L);
        }
        // catArticletaskTable.setForwardNum(readNumVO.getId());
        return success(catArticletaskTableService.updateTable(catArticletaskTable));
    }

    @ApiOperation("api-活动转发和分享")
    @PostMapping("activityForwardShare")
    public AjaxResult activityForwardShare(HttpServletRequest request, @RequestBody ActivityNumVO readNumVO) {

        CatActivityTable catArticletaskTable = new CatActivityTable();
        CatActivityTable catArticletaskTable1 = iCatActivityTableService.selectCatActivityTableById(readNumVO.getId());
        catArticletaskTable.setId(readNumVO.getId());
        if (catArticletaskTable1.getActivityForwardNum() != null) {
            catArticletaskTable.setActivityForwardNum(catArticletaskTable1.getActivityForwardNum() + 1);
        }else{
            catArticletaskTable.setActivityForwardNum(1L);
        }
        return success(iCatActivityTableService.updateCatActivityTable(catArticletaskTable1));
    }


    /**
     * Api文章新增
     * @param articletaskVO
     * @return
     */
    @ApiOperation("api-文章新增接口")
    @PostMapping("addArticle")
    public AjaxResult addArticle(HttpServletRequest request,@RequestBody ArticletaskVO articletaskVO)
    {
        WxLoginUser wxLoginUser = wxTokenService.getWxUser(request);
        CatArticletaskTable catArticletaskTable = new CatArticletaskTable();
        if (wxLoginUser != null){
            catArticletaskTable.setUserId(wxLoginUser.getUserId());
        }
        BeanUtils.copyProperties(articletaskVO, catArticletaskTable);
        catArticletaskTable.setCatArticlegiftTableList(articletaskVO.getCatArticlegiftTableList());
      //  articletaskVO.setEndTime(new Date() + 24 * 60 * 60 * 1000);
        catArticletaskTable.setEndTime(Date.from(Instant.now().plus(7, ChronoUnit.DAYS)));
        catArticletaskTable.setForwardNum(10000L);

        return toAjax(catArticletaskTableService.insertCatArticletaskTableApi(catArticletaskTable));
    }

    @ApiOperation("api-获取富文本页面")
    @GetMapping("/{id}")
    public ResponseEntity<String> generateVirtualPage(@PathVariable Long id) {
        try {
            //访问哟啊记录用户的ip等信息
            System.out.println(IpUtils.getHostIp());
            String htmlContent = richTextService.generateVirtualPage(id);
            HttpHeaders headers = new HttpHeaders();
            headers.setContentType(MediaType.TEXT_HTML);
            return new ResponseEntity<>(htmlContent, headers, HttpStatus.OK);
        } catch (Exception e) {
            return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body("页面生成失败");
        }
    }

    @ApiOperation("api-获取除了富文本之外的内容标题信息等")
    @GetMapping("getArticleInfo")
    public AjaxResult getArticleInfo(Long id) {
       return success(catArticletaskTableService.selectCatArticletaskTableById(id));
    }

    @ApiOperation("获取文章列表")
    @GetMapping("getArticleList")
    public TableDataInfo getArticleList(String status) {
        startPage();
        List<CatArticletaskTable> list = catArticletaskTableService.selectCatArticletaskTableList(null);
        return getDataTable(list);
    }

    @ApiOperation("获取最新任务")
    @GetMapping("getLatestTasks")
    public AjaxResult getLatestTasks() {
        List<LatestTaskDTO> list = catArticletaskTableService.getLatestTasks();
        return success(list);
    }

    @ApiOperation("api-新增活动阅读量")
    @PostMapping("inputArticleReadNum")
    public AjaxResult inputReadNum(HttpServletRequest request, @RequestBody ActivityNumVO readNumVO) {
        log.info("活动阅读量----readNumVO----"+readNumVO);

        String ipAddress = IpUtils.getIpAddr(request);
        System.out.println("ipAddress2----"+ ipAddress);

        // 更新分享用户统计
        CatShareuserTable catShareuserTable = new CatShareuserTable();
        catShareuserTable.setUserId(readNumVO.getRecommendId());
        catShareuserTable.setArticleId(readNumVO.getId());
        catShareuserTable.setType("2");
        CatShareuserTable catShareuserTable1 = iCatShareuserTableService.getShareUser(catShareuserTable);


        // 使用百度API获取IP地址信息
       // IpRegion currentArea = getIpLocationFromBaidu(ipAddress);
        IpRegion currentArea = IpAddressUtil.parseIpLocation(ipAddress);

        // 检查IP是否被拉黑
        if (isIpBlacklistedA(ipAddress)) {
            return error("IP已被限制访问");
        }

        // 检查10秒内PV次数
        if (checkPvFrequencyA(ipAddress)) {
            // 添加IP到黑名单
            addToBlacklistA(ipAddress);
            return error("访问过于频繁，IP已被限制");
        }

        // 构建IP记录
        CatIprecordTable catIprecordTable = new CatIprecordTable();
        catIprecordTable.setIpValue(ipAddress);
        catIprecordTable.setArticleId(readNumVO.getId());
        catIprecordTable.setType("2");
        catIprecordTable.setIplabel(readNumVO.getIplabel());
        catIprecordTable.setShareUserId(readNumVO.getRecommendId());
        catIprecordTable.setOnlySign(readNumVO.getOnlySign());
        // 设置完整地址信息
        catIprecordTable.setAreaValue( currentArea.getCity());

        // 更新UV统计
        updateUvStatsA(readNumVO.getId(), ipAddress, currentArea.getCity());
        // 更新PV统计
        updatePvStatsA(readNumVO.getId(), ipAddress, currentArea.getCity());

        CatActivityTable articletaskDTO = iCatActivityTableService.selectCatActivityTableByIdTask(readNumVO.getId());

        if(articletaskDTO != null){
            CatActivityTable catArticletaskTable = new CatActivityTable();
            catArticletaskTable.setQuantity(articletaskDTO.getQuantity() + 1);
            catArticletaskTable.setId(readNumVO.getId());
            iCatActivityTableService.updateCatActivity(catArticletaskTable);
            if (catShareuserTable1 != null) {
                catShareuserTable1.setQuantity(catShareuserTable1.getQuantity() + 1);
                iCatShareuserTableService.updateCatShareuserTable(catShareuserTable1);
            } else {
                catShareuserTable.setQuantity(1L);
               // iCatShareuserTableService.insertCatShareuserTable(catShareuserTable);
            }
        }

        // 更新活动任务统计
        if (articletaskDTO != null) {
            CatActivityTable catArticletaskTable = new CatActivityTable();
            catArticletaskTable.setNumberVisitors(articletaskDTO.getNumberVisitors() + 1);
            catArticletaskTable.setId(articletaskDTO.getId());
            iCatActivityTableService.updateCatActivity(catArticletaskTable);
        }

        return success(iCatIprecordTableService.insertCatIprecordTable(catIprecordTable));
    }

    @ApiOperation("api-新增文章阅读量")
    @PostMapping("inputReadNum")
    public AjaxResult inputReadNum(HttpServletRequest request, @RequestBody ReadNumVO readNumVO) {
        String ipAddress = IpUtils.getIpAddr(request);
        System.out.println("ipAddress1----"+ ipAddress);

        log.info("文章阅读量----readNumVO----"+readNumVO);

        // 更新分享用户统计
        CatShareuserTable catShareuserTable = new CatShareuserTable();
        if (readNumVO.getRecommendId() != null){
            catShareuserTable.setUserId(readNumVO.getRecommendId());
        }else{
            catShareuserTable.setUserId(readNumVO.getUserId());
        }
        catShareuserTable.setArticleId(readNumVO.getActivityId());
        catShareuserTable.setType("1");
        CatShareuserTable catShareuserTable1 = iCatShareuserTableService.getShareUser(catShareuserTable);
        CatArticletaskTable articletaskTable = catArticletaskTableService.selectArticletaskById(readNumVO.getActivityId());

        IpRegion currentArea = IpAddressUtil.parseIpLocation(ipAddress);
        log.info("currentArea----"+currentArea);

        // 使用百度API获取IP地址信息
       // IpRegion currentArea = getIpLocationFromBaidu(ipAddress);

        if (catShareuserTable1 != null) {
            // 检查是否达到目标数量
            if (articletaskTable.getQuantity() >= articletaskTable.getTargetNum()){
                log.info("检查是否达到目标数量----"+readNumVO);
                CatArticletaskTable catArticletaskTable = new CatArticletaskTable();
                catArticletaskTable.setId(articletaskTable.getId());
                catArticletaskTable.setArticleExamine("3");
                catArticletaskTableService.updateAdvertTime(catArticletaskTable);
                CatIprecordTable catIprecordTable = new CatIprecordTable();
                catIprecordTable.setIpValue(ipAddress);
                catIprecordTable.setArticleId(readNumVO.getActivityId());
                catIprecordTable.setType("1");
                catIprecordTable.setIplabel(readNumVO.getIplabel());
                catIprecordTable.setShareUserId(1L);
                catIprecordTable.setOnlySign(readNumVO.getOnlySign());
                catIprecordTable.setAreaValue(currentArea.getCity());
                iCatIprecordTableService.insertCatIprecordTable(catIprecordTable);
                return success();
            }

            if (articletaskTable.getEndTime() != null && articletaskTable.getEndTime().before(new Date())) {
                CatArticletaskTable catArticletaskTable = new CatArticletaskTable();
                catArticletaskTable.setId(articletaskTable.getId());
                catArticletaskTable.setArticleExamine("3");
                catArticletaskTableService.updateAdvertTime(catArticletaskTable);
                CatIprecordTable catIprecordTable = new CatIprecordTable();
                catIprecordTable.setIpValue(ipAddress);
                catIprecordTable.setArticleId(readNumVO.getActivityId());
                catIprecordTable.setType("1");
                catIprecordTable.setIplabel(readNumVO.getIplabel());
                catIprecordTable.setShareUserId(1L);
                catIprecordTable.setOnlySign(readNumVO.getOnlySign());
                catIprecordTable.setAreaValue(currentArea.getCity());
                iCatIprecordTableService.insertCatIprecordTable(catIprecordTable);
                return success();
            }
            catShareuserTable1.setQuantity(catShareuserTable1.getQuantity() + 1);
            iCatShareuserTableService.updateCatShareuserTable(catShareuserTable1);
        } else {
            catShareuserTable.setQuantity(1L);
          //  iCatShareuserTableService.insertCatShareuserTable(catShareuserTable);
        }

        // 检查IP是否被拉黑
        if (isIpBlacklisted(ipAddress)) {
            return error("IP已被限制访问");
        }
        // 检查10秒内PV次数
        if (checkPvFrequency(ipAddress)) {
            // 添加IP到黑名单
            addToBlacklist(ipAddress);
            return error("访问过于频繁，IP已被限制");
        }
        // 构建IP记录
        CatIprecordTable catIprecordTable = new CatIprecordTable();
        catIprecordTable.setIpValue(ipAddress);
        catIprecordTable.setArticleId(readNumVO.getActivityId());
        catIprecordTable.setType("1");
        catIprecordTable.setIplabel(readNumVO.getIplabel());
        catIprecordTable.setShareUserId(readNumVO.getRecommendId());
        catIprecordTable.setOnlySign(readNumVO.getOnlySign());
        catIprecordTable.setAreaValue(currentArea.getCity());

        // 更新UV统计
        updateUvStats(readNumVO.getActivityId(), ipAddress, currentArea.getCity());
        // 更新PV统计
        updatePvStats(readNumVO.getActivityId(), ipAddress, currentArea.getCity());
        ArticletaskDTO articletaskDTO = catArticletaskTableService.selectCatArticletaskById(readNumVO.getActivityId());

        // 检查是否已存在相同记录
        CatIprecordTable catIprecord = iCatIprecordTableService.getIprecordTable(catIprecordTable);
        if (null != catIprecord && null != catIprecord.getId()) {
            catIprecord.setQuantity(catIprecord.getQuantity() + 1);
            iCatIprecordTableService.updateCatIprecordTable(catIprecord);
            CatArticletaskTable catArticletaskTable = new CatArticletaskTable();
            catArticletaskTable.setQuantity(articletaskDTO.getQuantity() + 1);
            catArticletaskTable.setId(readNumVO.getActivityId());
            catArticletaskTableService.updateVisitors(catArticletaskTable);
            return success();
        }

        // 更新文章任务统计
        if (articletaskDTO != null) {
            CatArticletaskTable catArticletaskTable = new CatArticletaskTable();
            if(articletaskDTO.getNumberVisitors() != null){
                catArticletaskTable.setNumberVisitors(articletaskDTO.getNumberVisitors() + 1);
            }else{
                catArticletaskTable.setNumberVisitors(1L);
            }
            catArticletaskTable.setId(articletaskDTO.getId());
            catArticletaskTableService.updateVisitors(catArticletaskTable);
        }

        return success(iCatIprecordTableService.insertCatIprecordTable(catIprecordTable));
    }


    /**
     * 通过百度API获取IP地址信息
     * @param ip IP地址
     * @return IP区域信息
     */
    public  IpRegion getIpLocationFromBaidu(String ip) {
        // 先从Redis缓存中查询是否已经请求过该IP
        String cacheKey = "ip_location:" + ip;
        Object cachedLocation = redisTemplate.opsForValue().get(cacheKey);
        if (cachedLocation != null) {
            return JSON.parseObject(cachedLocation.toString(), IpRegion.class);
        }

        // 如果缓存中没有，则调用百度API
        IpRegion ipRegion = new IpRegion();
        String url = "https://api.map.baidu.com/location/ip?ip=" + ip + "&coor=bd09ll&ak=cP6UPnl0Py6TVXzS6aS4s2hRegXcffCM";

        try {
            String result = HttpUtil.get(url);
            JSONObject jsonObject = JSONObject.parseObject(result);

            if (jsonObject.getInteger("status") == 0) {
                JSONObject content = jsonObject.getJSONObject("content");
                JSONObject addressDetail = content.getJSONObject("address_detail");

                ipRegion.setProvince(addressDetail.getString("province"));
                ipRegion.setCity(addressDetail.getString("city"));
                ipRegion.setDistrict(addressDetail.getString("district"));

                // 缓存结果，有效期30天
                redisTemplate.opsForValue().set(cacheKey, JSON.toJSONString(ipRegion), 30, TimeUnit.DAYS);
            } else {
                // API调用失败时设置默认值
                ipRegion.setProvince("未知");
                ipRegion.setCity("未知");
                ipRegion.setDistrict("未知");
            }
        } catch (Exception e) {
            log.error("百度IP定位API调用失败：" + e.getMessage());
            ipRegion.setProvince("未知");
            ipRegion.setCity("未知");
            ipRegion.setDistrict("未知");
        }

        return ipRegion;
    }

    // 检查IP访问频率
    private boolean checkPvFrequency(String ipAddress) {
        String key = "pv_frequency:" + ipAddress;
        Long count = redisTemplate.opsForValue().increment(key, 1);
        if (count == 1) {
            redisTemplate.expire(key, 10, TimeUnit.SECONDS);
        }
        return count != null && count > 10;
    }


    // 将IP添加到黑名单
    private void addToBlacklist(String ipAddress) {
        String key = "ip_blacklist:" + ipAddress;
        redisTemplate.opsForValue().set(key, "1", 24, TimeUnit.HOURS);
    }

    // 检查IP是否在黑名单中
    private boolean isIpBlacklisted(String ipAddress) {
        String key = "ip_blacklist:" + ipAddress;
        return Boolean.TRUE.equals(redisTemplate.hasKey(key));
    }

    private boolean isIpBlacklistedA(String ipAddress) {
        String key = "ip_blacklistA:" + ipAddress;
        return Boolean.TRUE.equals(redisTemplate.hasKey(key));
    }

    // 更新UV统计
    private void updateUvStats(Long articleId, String ipAddress, String area) {
        String dateStr = DateUtil.format(new Date(), "yyyy-MM-dd");
        String uvKey = "article:uv:" + articleId + ":" + dateStr;
        String areaUvKey = "article:uv:" + articleId + ":" + area + ":" + dateStr;

        // 使用HyperLogLog统计UV
        redisTemplate.opsForHyperLogLog().add(uvKey, ipAddress);
        redisTemplate.opsForHyperLogLog().add(areaUvKey, ipAddress);

        // 设置过期时间
        redisTemplate.expire(uvKey, 7, TimeUnit.DAYS);
        redisTemplate.expire(areaUvKey, 7, TimeUnit.DAYS);
    }

    // 更新PV统计
    private void updatePvStats(Long articleId, String ipAddress, String area) {
        String dateStr = DateUtil.format(new Date(), "yyyy-MM-dd");
        String pvKey = "article:pv:" + articleId + ":" + dateStr;
        String areaPvKey = "article:pv:" + articleId + ":" + area + ":" + dateStr;

        // 增加PV计数
        redisTemplate.opsForValue().increment(pvKey);
        redisTemplate.opsForValue().increment(areaPvKey);

        // 设置过期时间
        redisTemplate.expire(pvKey, 7, TimeUnit.DAYS);
        redisTemplate.expire(areaPvKey, 7, TimeUnit.DAYS);
    }



    // 检查IP访问频率
    private boolean checkPvFrequencyA(String ipAddress) {
        String key = "pv_frequencyA:" + ipAddress;
        Long count = redisTemplate.opsForValue().increment(key, 1);
        if (count == 1) {
            redisTemplate.expire(key, 10, TimeUnit.SECONDS);
        }
        return count != null && count > 10;
    }

    // 将IP添加到黑名单
    private void addToBlacklistA(String ipAddress) {
        String key = "ip_blacklist:" + ipAddress;
        redisTemplate.opsForValue().set(key, "1", 24, TimeUnit.HOURS);
    }


    private void updateUvStatsA(Long articleId, String ipAddress, String area) {
        String dateStr = DateUtil.format(new Date(), "yyyy-MM-dd");
        String uvKey = "article:uvA:" + articleId + ":" + dateStr;
        String areaUvKey = "article:uvA:" + articleId + ":" + area + ":" + dateStr;

        // 使用HyperLogLog统计UV
        redisTemplate.opsForHyperLogLog().add(uvKey, ipAddress);
        redisTemplate.opsForHyperLogLog().add(areaUvKey, ipAddress);

        // 设置过期时间
        redisTemplate.expire(uvKey, 7, TimeUnit.DAYS);
        redisTemplate.expire(areaUvKey, 7, TimeUnit.DAYS);
    }

    // 更新PV统计
    private void updatePvStatsA(Long articleId, String ipAddress, String area) {
        String dateStr = DateUtil.format(new Date(), "yyyy-MM-dd");
        String pvKey = "article:pvA:" + articleId + ":" + dateStr;
        String areaPvKey = "article:pvA:" + articleId + ":" + area + ":" + dateStr;

        // 增加PV计数
        redisTemplate.opsForValue().increment(pvKey);
        redisTemplate.opsForValue().increment(areaPvKey);

        // 设置过期时间
        redisTemplate.expire(pvKey, 7, TimeUnit.DAYS);
        redisTemplate.expire(areaPvKey, 7, TimeUnit.DAYS);
    }

}
